package com.jeesite.common.utils;

import com.alibaba.fastjson.JSON;
import com.egzosn.pay.common.http.HttpStringEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.util.EntityUtils;

import java.util.Map;

/**
 * @ClassName HttpClientUtils
 * @Description 封装的HTTP客户端
 * @Author Spencer Zhang
 * @Date 2019/7/24 0026 9:55
 */
@Slf4j
public class HttpClientUtils {
    private static String PROXY_HOST = "";
    private static int PROXY_PORT = 8080;
    private static boolean USE_PROXY = false;
    // 缓存当前线程连接
    private static final ThreadLocal<CloseableHttpClient> CLIENT = new ThreadLocal();
    //缓存cookie
    private static final ThreadLocal<BasicCookieStore> COOKIE_STORE = new ThreadLocal();

    public static void createClient() {
        CloseableHttpClient client;
        HttpHost proxy;
        DefaultProxyRoutePlanner routePlanner = null;
        if (USE_PROXY) {//使用代理上网
            proxy = new HttpHost(PROXY_HOST, PROXY_PORT);
            routePlanner = new DefaultProxyRoutePlanner(proxy);
        }
        BasicCookieStore cookieStore = new BasicCookieStore();
        client = USE_PROXY ?
                HttpClients.custom().setDefaultCookieStore(cookieStore).setRoutePlanner(routePlanner).build()
                :
                HttpClients.custom()
                        .setDefaultCookieStore(cookieStore)
                        .setRetryHandler((e, i, httpContext) -> {
                            if (i > 3) {
                                log.error("Maximum tries reached for client http pool ");
                                return false;
                            }

                            if (e instanceof NoHttpResponseException     //NoHttpResponseException 重试
                                    || e instanceof ConnectTimeoutException //连接超时重试
//              || exception instanceof SocketTimeoutException    //响应超时不重试，避免造成业务数据不一致
                                    ) {
                                log.error("NoHttpResponseException on " + i + " call");
                                return true;
                            }
                            return false;
                        })
                        .build();

        CLIENT.set(client);
        COOKIE_STORE.set(cookieStore);
    }


    public static CloseableHttpClient getCurrentClient() {
        return CLIENT.get();
    }

    public static BasicCookieStore getCurrentCookie() {
        return COOKIE_STORE.get();
    }

    public static void closeConnection() {
        CloseableHttpClient client = getCurrentClient();
        if (client != null) {
            try {
                client.close();
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    public static void closeResponse(CloseableHttpResponse response) {
        if (response != null) {
            try {
                response.close();
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
    }

    public static <T> T sendMsg(String type, String uri, Map<String, Object> params, Class<T> t) {
        HttpClientUtils.createClient();
        CloseableHttpClient httpclient = HttpClientUtils.getCurrentClient();
        CloseableHttpResponse response = null;
        try {
            HttpUriRequest request;
            switch (type) {
                case "get":
                    StringBuilder s = new StringBuilder(uri);
                    int i = 0;
                    for (String key : params.keySet()) {
                        if (i == 0)
                            s.append("?");
                        else
                            s.append("&");
                        s.append(key + "=" + params.get(key));
                        i++;
                    }
                    request = new HttpGet(s.toString());
                    break;
                case "post":
                    request = new HttpPost(uri);
                    String body = "{";
                    for (String key : params.keySet()) {
                        body += "\"" + key + "\":" + "\"" + params.get(key) + "\"";
                    }
                    body += "}";
                    request.addHeader("Content-Type", "application/json");
                    HttpStringEntity entity = new HttpStringEntity(body);
                    ((HttpPost) request).setEntity(entity);
                    break;
                default:
                    throw new Exception("参数错误");
            }
            response = httpclient.execute(request);// 发送请求
            return JSON.parseObject(EntityUtils.toString(response.getEntity()), t);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            HttpClientUtils.closeResponse(response);
        }
        return null;
    }

}
